package documents

import (
	mgo "ez/vend/mongo"
	doc "ez/vend/mongo/base"
	"ez/vend/tool"
"encoding/json"
	ctx "context"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
	"reflect"
)

func (doc *{{ table.name }}) DocName() string             { return "{{ table.name }}" }

func (doc *{{ table.name }}) GetId() primitive.ObjectID   { return doc.Id }

func (doc *{{ table.name }}) SetId(id primitive.ObjectID) { doc.Id = id }

func (this *{{ table.name }}) GetReflect() reflect.Type {
return reflect.TypeOf({{ table.name }}{})
}

func (this {{ table.name }}) New() *{{ table.name }} {
	model := new({{ table.name }})
	this.Trigger("{{ table.path }}.{{ table.name }}New",model)
	return model
}

func (this *{{ table.name }}) Delete() error {
	this.Trigger("{{ table.path }}.{{ table.name }}Delete",this)
	_,err := this.GetMgo().DeleteOne(ctx.TODO(), this)
	return err
}
func (this *{{ table.name }}) Save(kvs ...map[string]interface{}) error {
	if this.Id.IsZero() {
		//if !this.GetEventBusOff() {
		//    ez.DispatchToMany("Before{{ table.name }}Create", this, &context.Context{})
		//}
		this.Trigger("{{ table.path }}.Before{{ table.name }}Create",this)
		err := this.GetMgo().InsertOne(ctx.TODO(), this)
		if err != nil {
			return err
		}
		//if !this.GetEventBusOff() {
		//    ez.DispatchToMany("After{{ table.name }}Create", this, &context.Context{})
		//}
		this.Trigger("{{ table.path }}.After{{ table.name }}Create",this)
	} else {
		//if !this.GetEventBusOff() {
		//    ez.DispatchToMany("Before{{ table.name }}Update", this, &context.Context{})
		//}
		this.Trigger("{{ table.path }}.Before{{ table.name }}Update",this)
		update := make(bson.D, 0)
		if len(kvs)==0 {
			for index, value := range this.ToArray() {
				if index == "id" {
					continue
				}
				update = append(update, bson.E{index, value})
			}
		}else {
			for _, kv := range kvs {
				for index, value := range kv {
					if index == "id" {
						continue
					}
					update = append(update, bson.E{index, value})
				}
			}
		}
		_, err := doc.GetStore(this.DocName()).UpdateOne(ctx.TODO(), ez.M{"_id": this.Id}, bson.M{"$set": update})
		if err != nil {
			return err
		}
		//if !this.GetEventBusOff() {
		//    ez.DispatchToMany("After{{ table.name }}Update", this, &context.Context{})
		//}
		this.Trigger("{{ table.path }}.After{{ table.name }}Update",this)
	}
	return nil
}

func (this *{{ table.name }}) ToArray() map[string]interface{} {
	data := ez.StringKeyMap{}
	data["id"] = this.Id
{% for f in fields %}
	data["{{ f.Name }}"] = this.{{ f.Name | capitalize }}
{% endfor %}
	return data
}

func (this *{{ table.name }}) CreateFromObject(jsonData interface{}) *{{ table.name }} {
tableByte, err := json.Marshal(jsonData)
if err != nil {
println(err.Error())
}
err = json.Unmarshal(tableByte, this)
if err != nil {
println(err.Error())
}
return this
}
func (this *{{ table.name }}) CreateFromString(jsonString string) *{{ table.name }} {
_ = json.Unmarshal([]byte(jsonString), this)
return this
}
func (this *{{ table.name }}) ToString() string {
ret, _ := json.Marshal(this)
return string(ret)
}
/***************************************
			Repository
****************************************/
type {{ table.name }}Repository struct {
doc.BaseCrud
}

func (this *{{ table.name }}Repository) GetQuerySetter() *mongo.Collection {
	m := new({{ table.name }})
	return this.GetStore(m.DocName())
}

func (rep {{ table.name }}Repository) Find(id string) {{ table.name }} {
	filter := ez.DbCreateFilter()
	filter["_id"],_ = primitive.ObjectIDFromHex(id)
	return rep.FindOneBy(filter, nil)
}

func (rep {{ table.name }}Repository) FindOneBy(filters map[string]interface{}, orderbys []string) {{ table.name }} {
	model := {{ table.name }}{}
	qs := rep.GetQuerySetter()
	rst := qs.FindOne(ctx.TODO(), doc.CreateFilter(filters), doc.CreateFindOneOption(orderbys))
	err := rst.Decode(&model)
	if err != nil {}
	return model
}

func (rep {{ table.name }}Repository) FindBy(filters map[string]interface{}, orderbys []string, limit int, offset int) []{{ table.name }} {
	var re []{{ table.name }}
	qs := rep.GetQuerySetter()
	rst, err := qs.Find(ctx.TODO(), doc.CreateFilter(filters), doc.CreateOption(orderbys, offset, limit))
	if err != nil {return re}
	errd := rst.All(ctx.TODO(), &re)
	if errd != nil {return re}
	return re
}

func (rep {{ table.name }}Repository) FindAll(orderbys []string) []{{ table.name }} {
	var re []{{ table.name }}
	qs := rep.GetQuerySetter()
	rst, err := qs.Find(ctx.TODO(), doc.CreateFilter(nil), doc.CreateOption(orderbys, 0, 0))
	if err != nil {return re}
	errd := rst.All(ctx.TODO(), &re)
	if errd != nil {return re}
	return re
}

func (rep {{ table.name }}Repository) GetList(builder *mgo.QueryBuilder) ([]*{{ table.name }}, error) {
	var re []*{{ table.name }}
	qs := rep.GetQuerySetter()
	rst, err := qs.Find(ctx.TODO(),
		doc.CreateFilter(builder.GetFilter()),
		doc.CreateOption(builder.GetOrder(), builder.GetOffset(), builder.GetLimit()))
	if err != nil {return nil, err}
	errd := rst.All(ctx.TODO(), &re)
	if errd != nil {return nil, err}
	//计数
	count,_:=qs.CountDocuments(ctx.TODO(),
		doc.CreateFilter(builder.GetFilter()),nil)
	builder.Total = count
	return re, nil
}